<!DOCTYPE html>
<meta charset="utf-8">
<title>Slowparse Demo</title>
<link rel="stylesheet" href="hierarchic-source-code.css">
<link rel="stylesheet" href="../vendor/codemirror2/lib/codemirror.css">
<link rel="stylesheet" href="jsbin-codemirror-theme.css">
<style>
html, body {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  height: 100%;
  margin: 0px;
  padding: 0px;
}

textarea.html {
  width: 100%;
  height: 200px;
}

.column {
  width: 25%;
  height: 100%;
  display: inline-block;
  vertical-align: top;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  border-left: 1px dotted black;
  padding-left: 10px;
  padding-right: 10px;
}

.column:first-child {
  border-left: none;
}

.column > aside {
  height: 6em;
  font-size: small;
}

.error {
  color: firebrick;
}

.error em[data-highlight] {
  font-style: inherit;
  color: red;
  text-decoration: underline;
  cursor: pointer;
}
</style>
<div class="column">
  <h2>HTML Source</h2>
  <aside>Tinker with this.</aside>
  <textarea class="html">&lt;p class="foo"&gt;hi&lt;/i&gt;</textarea>
</div><div class="column">
  <h2>DOM Diagram</h2>
  <aside>This is the DOM generated by <a href="..">slowparse</a>. Mouse over different parts to see where they correspond in the original source.</aside>
  <div class="rendered-dom"></div>
</div><div class="column">
  <h2>DOM Rendering</h2>
  <aside>This is what the DOM looks like on the Web.</aside>
  <div class="dom"></div>
</div><div class="column">
  <h2>Errors</h2>
  <aside>If any errors occurred while parsing, they will be shown here. Also see the <a href="../spec/">spec</a>.</aside>
  <div class="error"></div>
</div>
<script src="../vendor/jquery.min.js"></script>
<script src="../vendor/codemirror2/lib/codemirror.js"></script>
<script src="../vendor/codemirror2/mode/xml/xml.js"></script>
<script src="../vendor/codemirror2/mode/javascript/javascript.js"></script>
<script src="../vendor/codemirror2/mode/css/css.js"></script>
<script src="../vendor/codemirror2/mode/htmlmixed/htmlmixed.js"></script>
<script src="../slowparse.js"></script>
<script src="utils.js"></script>
<script src="tag-colors.js"></script>
<script src="render-dom.js"></script>
<script src="../spec/errors.jquery.js"></script>
<script>
var editor;

function selectInterval(interval) {
  var start = editor.coordsFromIndex(interval.start);
  var end = editor.coordsFromIndex(interval.end);
  editor.setSelection(start, end);
  editor.focus();
}

function linkRenderedDomToSource(rendered) {
  function getDottedName(obj, dottedName) {
    var parts = dottedName.split(".");
    for (var i = 0; i < parts.length; i++) {
      if (parts[i] in obj)
        obj = obj[parts[i]];
      else
        return null;
    }
    return obj;
  }
  
  function highlighter(property) {
    return function(event) {
      var linked = $(this).data("linked-node");
      if (!linked)
        linked = $(this).parent().data("linked-node");
      if (linked) {
        var interval = getDottedName(linked, property);
        if (interval) {
          selectInterval(interval);
          event.stopPropagation();
        }
      }
    }
  }
  
  rendered.find(".text")
    .mouseover(highlighter("parseInfo"));
  rendered.find(".element .start")
    .mouseover(highlighter("parseInfo.openTag"));
  rendered.find(".element .end")
    .mouseover(highlighter("parseInfo.closeTag"));
  rendered.find(".element .attributes .name")
    .mouseover(highlighter("parseInfo.name"));
  rendered.find(".element .attributes .value")
    .mouseover(highlighter("parseInfo.value"));
}

function processHTML(html) {
  $(".dom, .rendered-dom, .error").empty();
  
  try {
    var result = Slowparse.HTML(document, html);
  } catch (e) {
    console.error(e);
    $(".error").text(e.message);
    return;
  }
  var div = $("<div></div>").append($(result.document).contents());
  var rendered = div.renderDom();
  rendered.css({
    backgroundColor: "white",
    border: "none"
  }).find("> .start, > .end").remove();
  $(".dom").append(div);
  $(".rendered-dom").append(rendered);
  linkRenderedDomToSource(rendered);
  if (result.error) {
    try {
      $(".error").fillError(result.error);
    } catch (e) {
      $(".error").text(e.message);
    }
  }
}

$(document).on("mouseover", "[data-highlight]", function(event) {
  selectInterval($(this).errorHighlightInterval());
});

$(window).ready(function() {
  jQuery.loadErrors("../spec/", ["base"], function() {
    function onChange() {
      processHTML(editor.getValue());
    }
  
    editor = CodeMirror.fromTextArea($(".html")[0], {
      mode: "text/html",
      theme: "jsbin",
      tabMode: "indent",
      lineWrapping: true,
      lineNumbers: true,
      onChange: onChange
    });

    editor.focus();
    onChange();
  });
});
</script>